package com.nineclock.system.service.impl;

import java.util.Date;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.filter.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.dto.SysDepartmentDTO;
import com.nineclock.system.excel.ExcelMember;
import com.nineclock.system.listener.ExcelMemberListener;
import com.nineclock.system.mapper.*;
import com.nineclock.system.pojo.*;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.dto.SysRoleDTO;
import com.nineclock.system.service.SysCompanyUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class SysCompanyUserServiceImpl implements SysCompanyUserService {

    @Autowired
    private SysCompanyUserMapper companyUserMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysDepartmentMapper departmentMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysCompanyUserRoleMapper companyUserRoleMapper;


    @Override
    public List<SysCompanyUserDTO> queryCompanyUser(Long userId, Long companyId) {
        // 根据用户id、企业id查询员工信息
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getUserId, userId);
        if (companyId != null) {
            wrapper.eq(SysCompanyUser::getCompanyId, companyId);
        }
        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(wrapper);

        if (CollectionUtils.isEmpty(companyUserList)) {
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }

        // 数据转换，将 List<SysCompanyUser> ---> List<SysCompanyUserDTO>
        List<SysCompanyUserDTO> companyUserDTOList = BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);

        // 遍历员工信息，查询每个员工对应的角色、权限
        for (SysCompanyUserDTO sysCompanyUserDTO : companyUserDTOList) {
            // 根据员工id查询角色信息
            List<SysRole> roleList = roleMapper.queryRoleByCompanyUserId(sysCompanyUserDTO.getId());
            sysCompanyUserDTO.setRoles(BeanHelper.copyWithCollection(roleList, SysRoleDTO.class));

            // 根据角色id查询对应的权限信息

        }
        return companyUserDTOList;
    }

    @Override
    public List<SysCompanyUserDTO> queryCompanyMemberList() {
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrapper.eq(SysCompanyUser::getEnable, 1);
        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(wrapper);

        // 数据转换
        List<SysCompanyUserDTO> companyUserDTOList = BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
        return companyUserDTOList;
    }

    @Override
    public SysCompanyUserDTO queryCompanyUserById(Long companyUserId) {
        SysCompanyUser companyUser = companyUserMapper.selectById(companyUserId);
        return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
    }

    @Override
    public List<SysCompanyUserDTO> queryAllCompanyUser() {
        LambdaQueryWrapper<SysCompanyUser> wrappper = new LambdaQueryWrapper<>();
        wrappper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrappper.eq(SysCompanyUser::getEnable, 1);

        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(wrappper);

        return BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
    }

    @Override
    public PageResult<SysCompanyUserDTO> queryMembers(Integer page, Integer pageSize, Long departmentId, String keyword) {
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();

        // 判断部门id，如果不为空，递归查询所有的子部门id
        if (departmentId != null) {
            List<Long> departmentIdList = new ArrayList<>();
            departmentIdList.add(departmentId);
            queryAllChildDeparmentIds(departmentId, departmentIdList);
            // 员工的部门id 在 部门id集合中
            wrapper.in(SysCompanyUser::getDepartmentId, departmentIdList);
        }

        // 判断keyword，如果不为空，构造条件，用户名 或 手机号 或 工号 like keyword
        if (!StringUtils.isEmpty(keyword)) {
            // and (username like xxx or mobile like xxx or workNumber like xxx)
            wrapper.and(w -> {
                w.like(SysCompanyUser::getUserName, keyword)
                        .or()
                        .like(SysCompanyUser::getMobile, keyword)
                        .or()
                        .like(SysCompanyUser::getWorkNumber, keyword);

            });
        }

        // 分页查询员工表
        IPage<SysCompanyUser> ipage = new Page<>(page, pageSize);

        ipage = companyUserMapper.selectPage(ipage, wrapper);

        // 获取当前页的数据
        List<SysCompanyUser> companyUserList = ipage.getRecords();

        // 遍历当前页数据，设置DTO
        if (!CollectionUtils.isEmpty(companyUserList)) {

            List<SysCompanyUserDTO> companyUserDTOList = companyUserList.stream().map(sysCompanyUser -> {
                SysCompanyUserDTO companyUserDTO = BeanHelper.copyProperties(sysCompanyUser, SysCompanyUserDTO.class);

                // 前端需要
                SysDepartmentDTO departmentDTO = new SysDepartmentDTO();
                departmentDTO.setId(companyUserDTO.getDepartmentId());
                departmentDTO.setName(companyUserDTO.getDepartmentName());
                companyUserDTO.setDepartment(departmentDTO);

                return companyUserDTO;
            }).collect(Collectors.toList());

            return new PageResult<>(ipage.getTotal(), ipage.getPages(), companyUserDTOList);
        }
        // 封装返回结果
        return new PageResult<>(ipage.getTotal(), ipage.getPages(), null);
    }


    /**
     * 递归查询子部门id
     * @param departmentId
     * @param departmentIdList
     */
    private void queryAllChildDeparmentIds(Long departmentId, List<Long> departmentIdList) {
        LambdaQueryWrapper<SysDepartment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDepartment::getParentId, departmentId);
        wrapper.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
        List<SysDepartment> childList = departmentMapper.selectList(wrapper);

        if (!CollectionUtils.isEmpty(childList)) {
            for (SysDepartment department : childList) {
                departmentIdList.add(department.getId()); // 添加子部门id

                queryAllChildDeparmentIds(department.getId(), departmentIdList);
            }
        }
    }


    @Override
    public void importData(MultipartFile excelFile) throws Exception {
        // A. 通过SpringMVC接收上传上来的文件，并对文件进行健壮性判断
        if (excelFile == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        // B. 通过EasyExcel来解析Excel文件，获取文件内容
        EasyExcel.read(excelFile.getInputStream(),
                ExcelMember.class, new ExcelMemberListener(this)).sheet(0).doRead();


    }

    @Override
    public void handleParsedData(List<ExcelMember> memberList) {

        for (ExcelMember excelMember : memberList) {
            // C. 需要判定手机号、邮箱是否已经被注册；判定员工工号是否被占用；
            pendingMobileAndEmailAndWorkNumer(excelMember);

            // D. 保存系统用户数据
            SysUser sysUser = new SysUser();
            sysUser.setUsername(excelMember.getName());
            sysUser.setPassword(new BCryptPasswordEncoder().encode("123456"));
            sysUser.setMobile(excelMember.getMobile());
            sysUser.setEmail(excelMember.getEmail());
            sysUser.setCreateTime(new Date());
            sysUser.setUpdateTime(new Date());
            sysUser.setStatus(excelMember.getEnable().equals("可用") ? (short) 1 : (short) 0);
            sysUser.setLastLoginCompanyId(CurrentUserHolder.get().getCompanyId());
            userMapper.insert(sysUser);

            // E. 保存企业员工数据
            SysCompanyUser companyUser = saveCompanyUser(excelMember, sysUser);

            // F. 维护企业员工关联的角色
            saveCompanyUserRole(excelMember, companyUser);
        }

    }


    /**
     * 保存员工、角色关系
     *
     * @param excelMember
     * @param companyUser
     */
    private void saveCompanyUserRole(ExcelMember excelMember, SysCompanyUser companyUser) {
        // 根据角色名称查询角色信息
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRole::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrapper.eq(SysRole::getRoleDesc, excelMember.getRoleName());
        SysRole sysRole = roleMapper.selectOne(wrapper);

        if (sysRole != null) {
            SysCompanyUserRole sysCompanyUserRole = new SysCompanyUserRole();
            sysCompanyUserRole.setCompanyUserId(companyUser.getId());
            sysCompanyUserRole.setRoleId(sysRole.getId());
            sysCompanyUserRole.setCompanyId(CurrentUserHolder.get().getCompanyId());
            companyUserRoleMapper.insert(sysCompanyUserRole);
        }

    }


    /**
     * 保存企业员工数据
     *
     * @param excelMember
     * @param sysUser
     */
    private SysCompanyUser saveCompanyUser(ExcelMember excelMember, SysUser sysUser) {
        SysCompanyUser companyUser = new SysCompanyUser();
        companyUser.setUserId(sysUser.getId());
        companyUser.setCompanyId(CurrentUserHolder.get().getCompanyId());
        companyUser.setCompanyName(CurrentUserHolder.get().getCompanyName());
        companyUser.setPost(excelMember.getPosition());
        companyUser.setWorkNumber(excelMember.getWorkNumber());
        companyUser.setEmail(excelMember.getEmail());
        companyUser.setOfficeAddress(excelMember.getWorkAddr());
        companyUser.setTimeEntry(new Date());
        companyUser.setRemark(excelMember.getDesc());
        companyUser.setEnable(excelMember.getEnable().equals("可用") ? (short) 1 : (short) 0);
        companyUser.setCreateTime(new Date());
        companyUser.setUpdateTime(new Date());
        companyUser.setMobile(excelMember.getMobile());
        companyUser.setUserName(excelMember.getName());

        // 根据部门名称查询部门
        LambdaQueryWrapper<SysDepartment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrapper.eq(SysDepartment::getName, excelMember.getDepartmentName());

        SysDepartment department = departmentMapper.selectOne(wrapper);

        if (department != null) {
            companyUser.setDepartmentId(department.getId());
            companyUser.setDepartmentName(department.getName());
        }
        companyUserMapper.insert(companyUser);

        return companyUser;
    }


    /**
     * 判定手机号、邮箱是否已经被注册；判定员工工号是否被占用；
     *
     * @param excelMember
     */
    private void pendingMobileAndEmailAndWorkNumer(ExcelMember excelMember) {
        // 判断手机号、邮箱是否已经被注册
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());

        // and (mobile = xxx or email = xxx)
        wrapper.and(w -> {
            w.eq(SysCompanyUser::getMobile, excelMember.getMobile())
                    .or()
                    .eq(SysCompanyUser::getEmail, excelMember.getEmail());

        });
        Integer count = companyUserMapper.selectCount(wrapper);

        if (count > 0) {
            throw new NcException(ResponseEnum.USER_MOBILE_EMAIL_EXISTS);
        }

        // 判断员工工号是否被占用
        LambdaQueryWrapper<SysCompanyUser> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrapper2.eq(SysCompanyUser::getWorkNumber, excelMember.getWorkNumber());
        Integer count2 = companyUserMapper.selectCount(wrapper2);

        if (count2 > 0) {
            throw new NcException(ResponseEnum.WROK_NUM_EXISTS);
        }

    }


    @Override
    public SysCompanyUserDTO findCompanyUserByMobile(String mobile) {
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getMobile, mobile);
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        SysCompanyUser companyUser = companyUserMapper.selectOne(wrapper);

        if (companyUser != null) {
            return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
        }
        return null;
    }

    @Override
    public Integer queryUserCountByDepartmentIds(List<Long> departmentIds) {
        // 统计所有的部门id
        List<Long> allIdList = new ArrayList<>();
        allIdList.addAll(departmentIds);

        for (Long departmentId : departmentIds) {
            queryAllChildDeparmentIds(departmentId, allIdList);
        }

        // 查询这些部门id下的员工数量
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(SysCompanyUser::getDepartmentId, allIdList);
        wrapper.eq(SysCompanyUser::getEnable, 1);

        Integer count = companyUserMapper.selectCount(wrapper);

        return count;
    }

    @Override
    public List<SysCompanyUserDTO> queryAllUserByCompanyId(Long companyId) {
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, companyId);
        wrapper.eq(SysCompanyUser::getEnable, 1);
        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(wrapper);
        if(!CollectionUtils.isEmpty(companyUserList)){
            return BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
        }
        return null;
    }

    @Override
    public SysCompanyUserDTO queryAdminByCompanyId(Long companyId) {
        SysCompanyUser currentAdmin = companyUserMapper.getCurrentAdmin(companyId);
        return BeanHelper.copyProperties(currentAdmin, SysCompanyUserDTO.class);
    }
}
